package com.zfy.im.server.handler;


import com.zfy.im.common.Const;
import com.zfy.im.common.ImPacket;
import com.zfy.im.common.ImSessionContext;
import com.zfy.im.common.packets.*;
import org.apache.commons.collections4.MapIterator;
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tio.core.Aio;
import org.tio.core.ChannelContext;
import org.tio.core.GroupContext;
import org.tio.core.ObjWithLock;
import org.tio.core.maintain.ClientNodes;
import org.tio.core.utils.SystemTimer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @author tanyaowu
 */
public class AuthReqHandler implements ImBsHandlerIntf {
    private static Logger log = LoggerFactory.getLogger(AuthReqHandler.class);

    //	private static final byte tokenIndex = 0;

    /**
     * 模拟用户id
     */
    private static final AtomicInteger mockUserid = new AtomicInteger();

    /**
     *
     */
    public AuthReqHandler() {

    }

    @Override
    public Object handler(ImPacket packet, ChannelContext<ImSessionContext, ImPacket, Object> channelContext) throws Exception {
        if (packet.getBody() == null) {
            throw new Exception("body is null");
        }

        AuthReqBody authReqBody = AuthReqBody.parseFrom(packet.getBody());
        String token = authReqBody.getToken();
        String deviceId = authReqBody.getDeviceId();
        String deviceInfo = authReqBody.getDeviceInfo();
        Long seq = authReqBody.getSeq();
        String sign = authReqBody.getSign();

        if (StringUtils.isBlank(deviceId)) {
            Aio.close(channelContext, "did is null");
            return null;
        }

        if (seq == null || seq <= 0) {
            Aio.close(channelContext, "seq is null");
            return null;
        }

        token = token == null ? "" : token;
        deviceInfo = deviceInfo == null ? "" : deviceInfo;

        String data = token + deviceId + deviceInfo + seq + Const.authkey;

//		try
//		{
//			String _sign = Md5.getMD5(data);
//			if (!_sign.equals(sign))
//			{
//				log.error("sign is invalid, {}, actual sign:{},expect sign:{}", channelContext.toString(), sign, _sign);
//				Aio.close(channelContext, "sign is invalid");
//				return null;
//			}
//		} catch (Exception e)
//		{
//			log.error(e.toString(), e);
//			Aio.close(channelContext, e.getMessage());
//			return null;
//		}

        DeviceType deviceType = authReqBody.getDeviceType();
        //此处模拟绑定用户，实际业务中，需要根据token获取当前用户后再绑定之
        Aio.bindUser(channelContext, token);
        ImPacket imRespPacket = new ImPacket();
        AuthRespBody.Builder builder = AuthRespBody.newBuilder();
        builder.setTime(SystemTimer.currentTimeMillis());
        builder.setResult(AuthResult.Auth_PROVED);
        List<UserInfo> userInfoList = userInfo(channelContext);
        for (int i = 0, l = userInfoList.size(); i < l; i++) {
            builder.addUser(userInfoList.get(i));
        }

        AuthRespBody authRespBody = builder.build();
        imRespPacket.setCommand(Command.COMMAND_AUTH_RESP);
        imRespPacket.setBody(authRespBody.toByteArray());

        Aio.send(channelContext, imRespPacket);

        return null;
    }


    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

    }

    private List<UserInfo> userInfo(ChannelContext channelContext) {
        GroupContext userGroup = channelContext.getGroupContext();
        ClientNodes users = userGroup.getClientNodes();
        ObjWithLock<DualHashBidiMap<String, ChannelContext>> objWithLock = users.getMap();
        org.apache.commons.collections4.bidimap.DualHashBidiMap contents = objWithLock.getObj();
        MapIterator<String, ChannelContext> it = contents.mapIterator();
        List<UserInfo> userInfoList = new ArrayList<>();

        while (it.hasNext()) {
            String key = it.next();
            ChannelContext value = (ChannelContext) contents.get(key);
            String[] iport = key.split(":");
            String ip = iport[0];
            String userid = value.getUserid();
            int port = Integer.parseInt(iport[1]);
            UserInfo user = UserInfo.newBuilder().setUserid(userid).setUserip(IP.newBuilder().setUserip(ip).setPort(port)).build();
            userInfoList.add(user);
        }

        return userInfoList;
    }
}
